home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_185 / examples / pgtb / pgtb.zoo / catch.a < prev    next >
Text File  |  1988-12-12  |  25KB  |  1,017 lines

  1. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. * |_o_o|\\  The Software Distillery                    *
  3. * |. o.| || Made available to the Amiga development community        *
  4. * | .  | || the author:                         BBS:    *
  5. * | o  | ||   Jim Cooper                (919)-471-6436  *
  6. * |  . |//                                *
  7. * ======                                *
  8. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  9. *
  10. * Original code:
  11. *    'c.a'        by Lattice, Inc.
  12. *
  13. * Modifications:
  14. *    'catch.a'    by Jim Cooper, of The Software Distillery
  15. *    'catchnr.a'    by Jim Cooper, of The Software Distillery
  16. *
  17. * C initial startup procedure under AmigaDOS
  18. *
  19. *************************************************************************
  20. * If you are using the Lattice Assembler:
  21. *
  22. * Use the following command line to make c.o
  23. * asm -u -iINCLUDE: -oc.o catch.a
  24. *
  25. * Use the following command line to make catch.o
  26. * asm -u -iINCLUDE: -dCATCH -dAUTOREQ catch.a
  27. *
  28. * Use the following command line to make catchnr.o
  29. * asm -u -iINCLUDE: -dCATCH -ocatchnr.o catch.a
  30. *
  31. *************************************************************************
  32. *
  33. * If you are using the CAPE Assembler from Inovatronics, or just Assem from
  34. * MetaComCo, you must remove the asterisk from the 'set' lines below to
  35. * obtain the output version of the program you desire.
  36. *
  37. * For example:
  38. *
  39. * To generate 'c.o', don't make any changes.
  40. *
  41. * To generate 'catch.o, remove the asterisk from the lines with CATCH and
  42. *  AUTOREQ.
  43. *
  44. * To generate 'catchnr.o' remove the asterisk from the line with CATCH.
  45. *
  46. * Also, if using CAPE, you can edit the string on the OBJFILE line to
  47. * represent the version of the file you are generating.
  48. *
  49. *************************************************************************
  50. *
  51.  
  52.     ifnd    CAPE
  53.     INCLUDE "exec/types.i"
  54.     INCLUDE "exec/alerts.i"
  55.     INCLUDE "exec/nodes.i"
  56.     INCLUDE "exec/lists.i"
  57.     INCLUDE "exec/ports.i"
  58.     INCLUDE "exec/libraries.i"
  59.     INCLUDE "exec/tasks.i"
  60.  
  61.     INCLUDE "libraries/dos.i"
  62.     endc
  63.  
  64.     INCLUDE "exec/memory.i"
  65.     INCLUDE "exec/execbase.i"
  66.     INCLUDE "libraries/dosextens.i"
  67.     INCLUDE "workbench/startup.i"
  68.     INCLUDE "intuition/intuition.i"
  69.  
  70. *************************************************************************
  71. * Library offsets - DOS
  72.  
  73. _LVOOpen        equ    -30
  74. _LVOClose        equ    -36
  75. _LVORead        equ    -42
  76. _LVOWrite        equ    -48
  77. _LVOSeek        equ    -66
  78. _LVOCurrentDir        equ    -126
  79.  
  80. * Library offsets - EXEC
  81.  
  82. _LVOForbid        equ    -132
  83. _LVOPermit        equ    -138
  84. _LVOAllocMem        equ    -198
  85. _LVOFreeMem        equ    -210
  86. _LVOAvailMem        equ    -216
  87. _LVOSetSignal        equ    -306
  88. _LVOGetMsg        equ    -372
  89. _LVOReplyMsg        equ    -378
  90. _LVOWaitPort        equ    -384
  91. _LVOCloseLibrary    equ    -414
  92. _LVOOpenLibrary        equ    -552
  93. _LVOGetCC        equ    -528
  94.  
  95. * Library offsets - Intuition
  96.  
  97. _LVOAutoRequest        equ    -348
  98.  
  99. *************************************************************************
  100.  
  101.  
  102.     ifd    CAPE
  103.      CSYMFMT
  104. **** edit the following line to reflect your choices
  105.      OBJFILE    'c.o'
  106.      OPTIMON    -1
  107.     endc
  108.  
  109.  
  110. VERSION     equ    1
  111. REVISION    equ    0
  112.  
  113. *CATCH        set    1
  114. *AUTOREQ     set    1
  115.  
  116.  
  117. MEMFLAGS    EQU    MEMF_CLEAR+MEMF_PUBLIC
  118. AbsExecBase    EQU    4
  119.  
  120. Call    macro
  121.     jsr    _LVO\1(a6)
  122.     endm
  123.  
  124.     xdef    XCEXIT        ; exit(code) is standard way to leave C.
  125.     ifnd    CAPE
  126.      xdef     @XCEXIT
  127.     endc
  128.  
  129. * I am using a BETA of CAPE 2.0, and it doesn't like '@' in symbol names.
  130. * This means I have to kludge and use FileZap on the output file.
  131.     ifd    CAPE
  132.      xdef    RCEXIT
  133.     endc
  134.  
  135.     xref    LinkerDB    ; linker defined base value
  136.     xref    _BSSBAS     ; linker defined base of BSS
  137.     xref    _BSSLEN     ; linker defined length of BSS
  138.  
  139. *    library references
  140.  
  141.     section    text,code
  142.  
  143.     xref    _main        ; Name of C program to start with.
  144.     xref    MemCleanup
  145.     xref    __fpinit    ; initialize floating point
  146.     xref    __fpterm    ; terminate floating point
  147.  
  148. start:
  149.     movem.l    d1-d6/a0-a6,-(a7)
  150. REGSIZE EQU    (6+7)*4
  151.     lea    REGSIZE(a7),A5        ; determine old stack pointer
  152.     move.l    a0,a2            ; save command pointer
  153.     move.l    d0,d2            ; and command length
  154.     lea    LinkerDB,a4        ; load base register
  155.     
  156.     lea    _BSSBAS,a3        ; get base of BSS
  157.     moveq    #0,d1
  158.     move.l    #_BSSLEN,d0        ; get length of BSS in longwords
  159.     bra.s    clr_lp            ; and clear for length given
  160. clr_bss move.l    d1,(a3)+
  161. clr_lp    dbf    d0,clr_bss
  162.     
  163.     move.l    AbsExecBase.W,a6
  164.     move.l    a6,SysBase(A4)
  165.  
  166.     ifd    CATCH
  167.      move.w    AttnFlags(a6),Environment+2(a4) ; save copy for dump
  168.     endc
  169.  
  170.     move.l    a7,_StackPtr(A4)    ; Save stack ptr
  171.     clr.l    WBenchMsg(A4)
  172.  
  173. *------ attempt to open DOS library:
  174.     bsr.w    openDOS
  175.  
  176.     ifd    CATCH
  177.      ifd    AUTOREQ
  178. *------ attempt to open Intuition library:
  179.       bsr.w    openIntui
  180.      endc
  181.     endc
  182.  
  183. *-----    clear any pending signals
  184.     moveq    #0,d0
  185.     move.l    #$00003000,d1
  186.     Call    SetSignal
  187.  
  188. *------ get the address of our task
  189.     move.l    ThisTask(a6),A3
  190.  
  191.     ifd    CATCH
  192.      move.l    A3,TaskID(a4)
  193.  
  194. *------ initialize exception handler
  195. *------ Remember to preserve the old handler first
  196.      move.l    TC_TRAPDATA(a3),oldtrapdata(A4)
  197.      move.l    TC_TRAPCODE(a3),d0    ; check current exception
  198.      move.l    d0,oldtrapcode(A4)
  199.      swap    d0
  200.      cmpi.w    #$fb,d0         ; see if points to ROM
  201.      ble.s    1$            ; somebody else (debugger?) has vector
  202.      move.l    #Exception,TC_TRAPCODE(a3)    ; install pointers to code
  203.      move.l    a4,TC_TRAPDATA(a3)    ; ...and data
  204. 1$:
  205.     endc
  206.  
  207. *------ are we running as a son of Workbench?
  208.     move.l    pr_CurrentDir(A3),curdir(A4)
  209.     tst.l    pr_CLI(A3)
  210.     beq    fromWorkbench
  211.  
  212. *=======================================================================
  213. *====== CLI Startup Code ===============================================
  214. *=======================================================================
  215. *
  216. * Entry: D2 = command length
  217. *    A2 = Command pointer
  218. fromCLI:
  219.     ifd    CATCH
  220.      moveq    #-1,d0
  221.      move.l    d0,Starter(a4)        ; non-zero means CLI
  222.      move.l    a5,StackTop(a4)
  223.     endc
  224.  
  225.     move.l    a5,D0            ; get top of stack
  226.     sub.l    4(a5),D0        ; compute bottom
  227.     add.l    #128,D0         ; allow for parms overflow
  228.     move.l    D0,_base(A4)        ; save for stack checking
  229.  
  230. *------ find command name:
  231.     move.l    pr_CLI(a3),a0
  232.     add.l    a0,a0            ; bcpl pointer conversion
  233.     add.l    a0,a0
  234.     move.l    cli_CommandName(a0),a1
  235.     ifd    CATCH
  236.     IFND    AUTOREQ
  237.      move.l    cli_StandardOutput(a0),GConsole(a4)    ; save output fh
  238.     ENDC
  239.     endc
  240.     add.l    a1,a1            ; bcpl pointer conversion
  241.     add.l    a1,a1
  242.  
  243. *------ collect parameters:
  244.     move.l    d2,d0            ; get command line length
  245.     moveq.l    #0,d1
  246.     move.b    (a1)+,d1
  247.     move.l    a1,_ProgramName(A4)
  248.     add.l    d1,d0            ; add length of command name
  249.     addq.l    #1,d0            ; allow for space after command
  250.  
  251.     clr.w    -(A7)            ; set null terminator for command line
  252.     addq.l    #1,D0            ; force to even number of bytes
  253.     andi.w    #$fffe,D0        ;(round up)
  254.     sub.l    D0,A7            ; make room on stack for command line
  255.     subq.l    #2,D0
  256.  
  257.     clr.w    0(A7,D0)
  258.  
  259. *------ copy command line onto stack
  260.     move.l    d2,d0            ; get command line length
  261.     subq.l    #1,d0
  262.     add.l    d1,d2
  263.  
  264. copy_line:
  265.     move.b    0(A2,D0.W),0(A7,D2.W)    ; copy command line to stack
  266.     subq.l    #1,d2
  267.     dbf    d0,copy_line
  268.     move.b    #' ',0(a7,d2.w)        ; add space between command and parms
  269.     subq.l    #1,d2
  270.  
  271. copy_cmd:
  272.     move.b    0(a1,d2.w),0(a7,d2.w)    ; copy command name to stack
  273.     dbf    d2,copy_cmd
  274.     move.l    A7,A1
  275.     move.l    A1,-(A7)        ; push command line address
  276.     bra.w    main            ; call C entrypoint
  277.  
  278. *=======================================================================
  279. *====== Workbench Startup Code =========================================
  280. *=======================================================================
  281.  
  282. fromWorkbench:
  283.     move.l    TC_SPLOWER(a3),_base(A4)    ; set base of stack
  284.     add.l    #128,_base(A4)        ; allow for parms overflow
  285.  
  286.     ifd    CATCH
  287.      move.l    TC_SPUPPER(a3),StackTop(a4)    ; set top of stack
  288.     endc
  289.  
  290. *------ we are now set up.  wait for a message from our starter
  291.     lea    pr_MsgPort(A3),a0    ; our process base
  292.     Call    WaitPort
  293.     lea    pr_MsgPort(A3),a0    ; our process base
  294.     Call    GetMsg
  295.     move.l    d0,WBenchMsg(a4)
  296.     move.l    d0,-(SP)
  297. *
  298.     move.l    d0,a2            ; get first argument
  299.     move.l    sm_ArgList(a2),d0
  300.     beq.s    do_cons
  301.     move.l    DOSBase(a4),a6
  302.     move.l    d0,a0
  303.     move.l    wa_Lock(a0),d1
  304.     move.l    d1,curdir(A4)
  305.     Call    CurrentDir
  306. do_cons:
  307.     move.l    sm_ToolWindow(a2),d1    ; get the window argument
  308.     beq.s    do_main
  309.     move.l    #MODE_OLDFILE,d2
  310.     Call    Open
  311.     move.l    d0,stdin(a4)
  312.     beq.s    do_main
  313.     lsl.l    #2,d0
  314.     move.l    d0,a0
  315.     move.l    fh_Type(a0),pr_ConsoleTask(A3)
  316. do_main:
  317.     move.l    WBenchMsg(A4),a0    ; get address of workbench message
  318.     move.l    a0,-(a7)        ; push argv
  319.     pea    NULL(a4)        ; push argc
  320.     move.l    sm_ArgList(a0),a0    ; get address of arguments
  321.     move.l    wa_Name(a0),_ProgramName(A4)    ; get name of program
  322.  
  323. *=============================================
  324. *------ common code --------
  325. *=============================================
  326.  
  327. main    jsr    __fpinit(PC)        ; Initialize floating point
  328.     jsr    _main(PC)        ; call C entrypoint
  329.     moveq.l    #0,d0            ; set successful status
  330.     bra.s    exit2
  331. *
  332.  
  333. XCEXIT:
  334.     move.l    4(SP),d0        ; extract return code
  335. RCEXIT:
  336. exit2:
  337.     move.l    d0,-(a7)
  338.  
  339.     move.l    _ONEXIT(A4),d0        ; exit trap function?
  340.     beq.s    exit3
  341.     move.l    d0,a0
  342.     jsr    (a0)
  343. exit3:
  344.     jsr    MemCleanup(PC)        ; cleanup leftover memory alloc.
  345.  
  346.     move.l    AbsExecBase.W,a6
  347.  
  348. *------ Restore the original exception handler
  349.     move.l    ThisTask(a6),A3
  350.     ifd    CATCH
  351.      move.l    oldtrapdata(A4),TC_TRAPDATA(a3)
  352.      move.l    oldtrapcode(A4),TC_TRAPCODE(a3)    ; check current exception
  353.     endc
  354.  
  355.     move.l    DOSBase(A4),a1
  356.     Call    CloseLibrary        ; close Dos library
  357.  
  358.     ifd    CATCH
  359.      ifd    AUTOREQ
  360.       move.l    IntuiBase(a4),a1
  361.       Call    CloseLibrary        ; close Intuition library
  362.      endc
  363.     endc
  364.  
  365.     jsr    __fpterm(PC)        ; clean up any floating point
  366.  
  367. done_1c:
  368. *------ if we ran from CLI, skip workbench cleanup:
  369.     tst.l    WBenchMsg(A4)
  370.     beq.s    exitToDOS
  371.     move.l    stdin(A4),d1
  372.     beq.s    done_4
  373.     Call    Close
  374. done_4:
  375.  
  376. *------ return the startup message to our parent
  377. *    we forbid so workbench can't UnLoadSeg() us
  378. *    before we are done:
  379.     move.l    AbsExecBase.W,A6
  380.     Call    Forbid
  381.     move.l    WBenchMsg(a4),a1
  382.     Call    ReplyMsg
  383.  
  384. *------ this rts sends us back to DOS:
  385. exitToDOS:
  386.     MOVE.L    (A7)+,D0
  387.     movea.l    _StackPtr(a4),SP    ; restore stack ptr
  388.     movem.l    (a7)+,d1-d6/a0-a6
  389.     rts
  390.  
  391.     
  392. *-----------------------------------------------------------------------
  393. noDOS:
  394.     moveq.l    #100,d0
  395.     bra.w    exit2
  396.  
  397.  
  398. *-----------------------------------------------------------------------
  399. *    Open the DOS library:
  400.  
  401. openDOS:
  402.     lea    DOSName(PC),A1
  403.     moveq.l    #0,D0
  404.     Call    OpenLibrary
  405.     move.l    D0,DOSBase(A4)
  406.     beq.s    noDOS
  407.     rts
  408. DOSName:
  409.      dc.b    'dos.library',0
  410.  
  411.     ifd    CATCH
  412. *-----------------------------------------------------------------------
  413. *    Open the Intuition library:
  414.  
  415. openIntui:
  416.     lea    IntuiName(PC),A1
  417.     moveq.l    #0,D0
  418.     Call    OpenLibrary
  419.     move.l    D0,IntuiBase(A4)
  420.     beq.s    noDOS
  421.     rts
  422. IntuiName:
  423.     dc.b    'intuition.library',0
  424.  
  425. *-----------------------------------------------------------------------
  426. *    The Exception Handler - catches GURUs and exits (semi)cleanly
  427. Exception:
  428.     move.l    AbsExecBase.W,a0
  429.     move.l    ThisTask(a0),a0
  430.     move.l    TC_TRAPDATA(a0),a0    ; ...and data
  431.  
  432.     move.l    (a7)+,d0        ; get exception # from stack
  433.     move.l    d0,GURUNum(a0)        ; and save it
  434.     cmpi.l    #3,d0            ; ADDRESS or BUS error?
  435.     bgt.s    2$            ; no, skip adjustment
  436.     btst    #0,Environment+3(a0)    ; is it 68010 or 68020?
  437.     beq.s    1$            ; 0 means NO
  438.     bset    #7,8(a7)        ; set Rerun flag
  439.     bra.s    2$
  440. 1$:
  441.     addq.l    #8,a7            ; adjust for 68000
  442. 2$:
  443.     move.l    2(a7),d0        ; get PC at crash
  444.     move.l    d0,GURUAddr(a0)        ; and save it
  445.     move.l    #GURUExit,2(a7)        ; use our own exit point
  446.     rte
  447.  
  448. *-----------------------------------------------------------------------
  449. *    The Exception exit routine - write 'PGTB' IFF FORM to file
  450. *    'SnapShot.TB' in current directory, then exit to system.
  451.  
  452. GURUExit:
  453.     movem.l    d0-d7/a0-a7,-(sp)    ; save all registers
  454.     move.l    AbsExecBase.W,a6    ; make sure we are working with Exec
  455.     Call    GetCC            ; safe way - works with all CPUs
  456.     move.l    ThisTask(a6),a3
  457.     move.l    TC_TRAPDATA(a3),a4    ; make sure we have a valid # in a4
  458.     move.l    d0,Flags(a4)        ; save area
  459.     movem.l    (sp)+,d0-d7
  460.     movem.l    d0-d7,DDump(a4)        ; save data reg contents
  461.     movem.l    (sp)+,d0-d7
  462.     movem.l    d0-d7,ADump(a4)        ; save address reg contents
  463.     tst.l    StackPtr(a4)        ; if there's something there
  464.     bne    GExit1            ; ...we've been here before!
  465.     lea    TempStore(a4),a0    ; calculate addr of TempStore
  466.     move.l    a0,TempAddr(a4)        ; ...and save for later access
  467.     move.l    A7Store(a4),d0        ; make sure we have proper TOS
  468.     move.l    d0,StackPtr(a4)        ; ...and save it
  469.     moveq    #0,d0
  470.     move.l    _ProgramName(a4),a0    ; find length of program name
  471.  
  472.     ifd    AUTOREQ
  473.      move.l    a0,PName(a4)
  474.     endc
  475.  
  476.     subq.l    #1,a0
  477.     move.b    (a0),d0
  478.     addq.l    #4,d0            ; adjust for shift
  479.     lsr.l    #2,d0
  480.     move.l    d0,NameLen(a4)        ; store length
  481.     add.l    d0,FAILlen(a4)        ; and sub-chunk total
  482.  
  483.     moveq    #0,d0            ; clear d0 for use
  484.     lea    VBlankFrequency(a6),a0    ; set up a0 to find correct data
  485.     move.b    (a0)+,d0        ; get just in case
  486.     move.l    d0,VBlankFreq(a4)    ; ...so we can figure what
  487.     move.b    (a0),d0            ; ...type of machine
  488.     move.l    d0,PowerSupFreq(a4)    ; ...we're working on
  489.  
  490.     lea    start-4(pc),a0        ; get seglist ptr
  491.     moveq    #-1,d0            ; always at least 1
  492. 2$:
  493.     addq.l    #1,d0
  494.     move.l    (a0),d1            ; find end of list
  495.     beq.s    3$
  496.     lsl.l    #2,d1            ; BPTR!!!!!
  497.     move.l    d1,a0
  498.     bra.s    2$
  499. 3$:
  500.     add.l    d0,SegCount(a4)        ; store # of seglist pointers
  501.     lsl.l    #1,d0            ; multiply by 2 for longword count
  502.     add.l    d0,FAILlen(a4)        ; and sub-chunk length
  503.  
  504.     move.l    StackTop(a4),d0        ; get top of stack
  505.     sub.l    StackPtr(a4),d0        ; find number of bytes used
  506.     addq.l    #4,d0            ; adjust for longword conversion
  507.     lsr.l    #2,d0            ; convert from bytes to long
  508.     move.l    d0,StackLen(a4)        ; and save
  509.     add.l    d0,s2len(a4)        ; and sub-chunk total
  510.  
  511.     move.l    a5,-(sp)        ; save a5 for later
  512.     Call    Forbid            ; don't let 'em change while we ask
  513.     move.l    MemList+LH_HEAD(a6),a0    ; first node in MemList
  514. checkchip:
  515.     move.w    MH_ATTRIBUTES(a0),d4    ; get node attributes
  516.     btst    #MEMB_CHIP,d4        ; is it chip?
  517.     beq.s    checkfast        ; no, go on
  518.     lea    chipAvail(a4),a3
  519.     bsr.w    AddIt
  520. checkfast:
  521.     btst    #MEMB_FAST,d4        ; is it fast?
  522.     beq.s    next            ; no, go on
  523.     lea    fastAvail(a4),a3
  524.     bsr.w    AddIt
  525. next:
  526.     tst.l    LN_SUCC(a0)
  527.     move.l    LN_SUCC(a0),a0        ; get address of next node
  528.     bne.s    checkchip        ; ...and loop back if valid
  529.     Call    Permit            ; allow others access again
  530.     move.l    #MEMF_CHIP+MEMF_LARGEST,d1 ; to find largest hunk in chip ram
  531.     Call    AvailMem
  532.     move.l    d0,chipLargest(a4)    ; store
  533.     move.l    #MEMF_FAST+MEMF_LARGEST,d1 ; to find largest hunk in fast ram
  534.     Call    AvailMem
  535.     move.l    d0,fastLargest(a4)    ; store
  536.     move.l    (sp)+,a5        ; and restore a5
  537.  
  538.     ifd    AUTOREQ
  539.     moveq    #0,d0            ; PosFlag
  540.     move.l    d0,d1            ; NegFlag
  541.     move.l    d0,a0            ; 0 means use current window
  542.     lea    IText1(a4),a1        ; Body Text
  543.     lea    IText5(a4),a2        ; Positive Gadget Text
  544.     lea    IText6(a4),a3        ; Negative Gadget Text
  545.     moveq    #1,d2
  546.     lsl.l    #8,d2            ; quick way to set Width
  547.     moveq    #76,d3            ; Height
  548.     move.l    IntuiBase(a4),a6    ; get intuition library pointer
  549.     Call    AutoRequest
  550.     move.l    AbsExecBase.W,a6
  551.     tst.l    d0            ; save SnapShot?
  552.     beq    GExit2            ; no, just exit
  553.     endc
  554.  
  555.     move.l    DOSBase(a4),a6
  556.     lea    DumpName(a4),a0        ; get name of output file
  557.     move.l    a0,d1
  558.     move.l    #MODE_NEWFILE,d2    ; create new file
  559.     Call    Open
  560.     bne.s    4$
  561.     lea    DumpPath(a4),a0        ; if error in current dir, try DF1:
  562.     move.l    a0,d1
  563.     move.l    #MODE_NEWFILE,d2
  564.     Call    Open
  565.     bne.s    4$
  566.     move.b    #'0',DumpPath+3(a4)    ; still error?    Try DF0:
  567.     lea    DumpPath(a4),a0
  568.     move.l    a0,d1
  569.     move.l    #MODE_NEWFILE,d2
  570.     Call    Open
  571.  
  572.     ifnd    AUTOREQ
  573.     bne.s    4$            ; if no error, continue (finally!)
  574.     move.l    GConsole(a4),d1
  575.     beq.w    GExit2
  576.     lea    failmsg(a4),a0
  577.     move.l    a0,d2
  578.     move.l    #23,d3
  579.     Call    Write
  580.     endc
  581.  
  582.     bra.w    GExit2            ; else, print msg & DIE gracefully
  583. 4$:
  584.     move.l    d0,d5            ; save file handle for Write
  585.     move.l    d0,fp(a4)        ; ...and in a safe place for later
  586.     move.l    d5,d1            ; get file handle
  587.     lea    PGTB(a4),a0        ; first part of fixed
  588.     move.l    a0,d2
  589.     move.l    #chunk_len_1,d3     ; length of first
  590.     Call    Write            ; ...since it gets written over
  591.  
  592.     move.l    d5,d1            ; get file handle
  593.     move.l    _ProgramName(a4),d2    ; get address of program name
  594.     move.l    NameLen(a4),d3        ; get # longs in program name
  595.     lsl.l    #2,d3            ; ..and convert to bytes
  596.     Call    Write
  597.  
  598.     move.l    d5,d1            ; get file handle
  599.     lea    Environment(a4),a0    ; second part of fixed
  600.     move.l    a0,d2
  601.     move.l    #chunk_len_2,d3     ; length of second part
  602.     Call    Write
  603.  
  604.     lea    start-8(pc),a0        ; address of seglist (size of seg)
  605.     move.l    (a0)+,d0        ; segsize
  606.     move.l    d0,TempStore+4(a4)    ; save it
  607.     move.l    a0,TempStore(a4)    ; store first number
  608.     move.l    SegCount(a4),d4
  609. 5$:
  610.     move.l    d5,d1            ; get file handle
  611.     move.l    TempAddr(a4),d2        ; address of write buffer
  612.     moveq    #TempSize,d3        ; size of segment pointer
  613.     Call    Write
  614.     move.l    TempStore(a4),a0    ; retrieve pointer
  615.     move.l    (a0),d0            ; get next seg pointer
  616.     lsl.l    #2,d0            ; adjust
  617.     move.l    d0,TempStore(a4)    ; ..and save
  618.     move.l    d0,a0
  619.     move.l    -4(a0),d0        ; get segsize
  620.     move.l    d0,TempStore+4(a4)    ; ...and save it
  621.     subq.l    #1,d4            ; done yet?
  622.     bne.s    5$            ; no, do next
  623.  
  624.     tst.l    _FMEM(a4)        ; do they want memory reported?
  625.     beq.s    55$            ; no, forget it
  626.     move.l    d5,d1
  627.     lea    subFMEM(a4),a0
  628.     move.l    a0,d2
  629.     move.l    #FMEMlen,d3
  630.     Call    Write
  631.  
  632. 55$:
  633.     move.l    d5,d1            ; (get the idea?)
  634.     lea    subREGS(a4),a0        ; third part of fixed
  635.     move.l    a0,d2
  636.     move.l    #chunk_len_3,d3     ; length of third
  637.     Call    Write
  638.  
  639.     move.l    StackLen(a4),d0        ; get length of stack used
  640.     cmpi.l    #2048,d0        ; > 8k ?
  641.     bgt.s    6$            ; yes, dump two chunks
  642.     move.l    d5,d1
  643.     lea    STAK2(a4),a0        ; whole stack chunk
  644.     move.l    a0,d2
  645.     moveq    #STAK2len,d3        ; length of fixed part
  646.     Call    Write
  647.  
  648.     move.l    d5,d1
  649.     move.l    StackPtr(a4),d2        ; address of stack
  650.     move.l    StackLen(a4),d3        ; get # longwords on stack
  651.     lsl.l    #2,d3            ; ..and convert to bytes
  652.     Call    Write
  653.     bra.s    7$
  654. 6$:
  655.     move.l    d5,d1
  656.     lea    STAK3(a4),a0        ; top4k chunk
  657.     move.l    a0,d2
  658.     moveq    #STAK3len,d3        ; length of fixed part
  659.     Call    Write
  660.  
  661.     move.l    d5,d1
  662.     move.l    StackTop(a4),d2        ; find top of stack
  663.     sub.l    #4096,d2        ; find top-4k
  664.     move.l    #4096,d3        ; # bytes to write
  665.     Call    Write
  666.  
  667.     move.l    d5,d1
  668.     lea    STAK4(a4),a0        ; bottom4k chunk
  669.     move.l    a0,d2
  670.     moveq    #STAK4len,d3        ; length of fixed part
  671.     Call    Write
  672.  
  673.     move.l    d5,d1
  674.     move.l    StackPtr(a4),d2        ; current stack address
  675.     move.l    #4096,d3        ; # bytes to write
  676.     Call    Write
  677. 7$:
  678.     move.l    _STAKOffset(a4),d3
  679.     beq.s    8$
  680.     lsr.l    #2,d3
  681.     addq.l    #1,d3
  682.     move.l    d3,_STAKOffset(a4)
  683.     addq.l    #1,d3
  684.     move.l    d5,d1
  685.     lea    STAK5(a4),a0
  686.     move.l    a0,d2
  687.     moveq    #STAK5len,d3
  688.     Call    Write
  689.  
  690.     move.l    d5,d1
  691.     move.l    StackPtr(a4),d2
  692.     move.l    _STAKOffset(a4),d3
  693.     subq.l    #1,d3
  694.     move.l    StackLen(a4),d4
  695.     cmp.l    d3,d4
  696.     bge.s    75$
  697.     move.l    StackLen(a4),d3
  698. 75$:
  699.     lsl.l    #2,d3
  700.     Call    Write
  701. 8$:
  702.     tst.l    _ONGURU(A4)        ; user GURU function?
  703.     beq.s    9$
  704.     move.l    d5,-(sp)
  705.     move.l    d5,d1
  706.     lea    UDAT(a4),a0
  707.     move.l    a0,d2
  708.     move.l    #UDATlen,d3
  709.     Call    Write
  710.     move.l    d5,d1
  711.     moveq    #0,d2            ; zero offset
  712.     moveq    #1,d3            ; ...from EOF
  713.     Call    Seek
  714.     move.l    d0,SeekStore(a4)
  715.     move.l    _ONGURU(a4),a0
  716.     jsr    (a0)
  717.     addq.l    #4,sp
  718. 9$:
  719.     move.l    fp(a4),d5
  720.     move.l    d5,d1
  721.     moveq    #0,d2            ; offset from EOF
  722.     moveq    #1,d3            ; OFFSET_END
  723.     Call    Seek            ; Seek returns OLD position
  724.     move.l    d0,d1
  725.     andi.l    #3,d1            ; did user write even longwords?
  726.     beq.s    10$            ; Yep!    Nice Human.
  727.     move.l    d1,d6            ; Nope, save for later.
  728.     clr.l    TempStore(a4)        ; clear temp storage
  729.     move.l    d5,d1
  730.     move.l    TempAddr(a4),d2
  731.     moveq    #4,d3
  732.     sub.l    d6,d3            ; find how many NULLs to pad
  733.     Call    Write
  734.     bra.s    9$
  735. 10$:
  736.     tst.l    SeekStore(a4)        ; did we write UDAT?
  737.     beq.s    11$            ; nope!
  738.     sub.l    SeekStore(a4),d0    ; find length of UDAT section
  739.     lsr.l    #2,d0            ; adjust to longwords
  740.     move.l    d0,TempStore(a4)    ; save UDAT length for write
  741.     move.l    d5,d1
  742.     move.l    SeekStore(a4),d2    ; find where to write it
  743.     subq.l    #4,d2
  744.     moveq    #-1,d3            ; OFFSET_BEGINNING
  745.     Call    Seek
  746.     move.l    d5,d1
  747.     move.l    TempAddr(a4),d2
  748.     move.l    #4,d3
  749.     Call    Write            ; write length of UDAT field to file
  750. 11$:
  751.     move.l    d5,d1
  752.     moveq    #0,d2
  753.     moveq    #1,d3            ; OFFSET_END
  754.     Call    Seek            ; make sure we are at end of file
  755.     move.l    d5,d1
  756.     moveq    #0,d2
  757.     moveq    #-1,d3            ; OFFSET_BEGINNING
  758.     Call    Seek
  759.     subq.l    #8,d0            ; adjust total length
  760.     lsr.l    #2,d0            ; adjust to longwords
  761.     move.l    d0,formLength(a4)    ; and store FORM length
  762.     subq.l    #2,d0            ; adjust for PGTB chunk length
  763.     move.l    d0,Length(a4)        ; and store it
  764.     move.l    d5,d1
  765.     move.l    PGTB(a4),d2
  766.     move.l    #16,d3
  767.     Call    Write            ; write revised FORM header
  768. GExit1:
  769.     move.l    fp(a4),d1
  770.     beq.s    GExit2
  771.     move.l    DOSBase(a4),a6
  772.     Call    Close
  773.  
  774.     ifnd    AUTOREQ
  775.     move.l    GConsole(a4),d1
  776.     beq.s    GExit2
  777.     lea    success(a4),a0
  778.     move.l    a0,d2
  779.     move.l    #32,d3
  780.     Call    Write
  781.     endc
  782. GExit2:
  783.     move.l    TaskID(a4),a6
  784.     move.l    AbsExecBase.W,a6
  785.     moveq    #$47,d0
  786.     bra.w    exit2
  787.  
  788. *-----------------------------------------------------------------------
  789. * AddIt:    routine to add memory parts to variables
  790.  
  791. AddIt:
  792.     move.l    MH_FREE(a0),d0
  793.     add.l    d0,(a3)            ; add to available
  794.     move.l    MH_UPPER(a0),d0
  795.     sub.l    MH_LOWER(a0),d0
  796.     add.l    d0,4(a3)        ; add to Max section
  797.     rts
  798.     endc
  799.  
  800.     
  801.     section    __MERGED,DATA
  802. *
  803.     xdef    NULL,SysBase,WBenchMsg
  804.     xdef    curdir,_mbase,_mnext,_msize,_tsize
  805.     xdef    _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  806.     xdef    _SIGINT
  807.     xdef    _ProgramName,_StackPtr,_base
  808.  
  809.     ifd    CATCH
  810.     xdef    _ONGURU,_FMEM,_STAKOffset
  811.     endc
  812. *
  813. NULL        dc.l    0        ;
  814. _base        dc.l    0        ; base of stack
  815. _mbase        dc.l    0        ; base of memory pool
  816. _mnext        dc.l    0        ; next available memory location
  817. _msize        dc.l    0        ; size of memory pool
  818. _tsize        dc.l    0        ; total size?
  819. _oserr:
  820. _OSERR        dc.l    0
  821. _FPERR        dc.l    0
  822. _SIGFPE     dc.l    0
  823. _SIGINT     dc.l    0
  824. _ONERR        dc.l    0
  825. _ONEXIT     dc.l    0
  826. _ONBREAK    dc.l    0
  827. curdir        dc.l    0
  828. SysBase     dc.l    0
  829. DOSBase        dc.l    0
  830. WBenchMsg    dc.l    0
  831. _StackPtr    dc.l    0
  832. stdin        dc.l    0
  833. _ProgramName    dc.l    0
  834.  
  835.     ifd    CATCH
  836. oldtrapcode    dc.l    0
  837. oldtrapdata    dc.l    0
  838. _ONGURU     dc.l    0
  839. IntuiBase    dc.l    0
  840. TaskID        dc.l    0
  841.     ifnd    AUTOREQ
  842. GConsole    dc.l    0
  843. failmsg     dc.b    7,'Can''t write SnapShot!',10
  844. success     dc.b    7,'GURU caught; SnapShot written!',10
  845.     endc
  846.     cnop    0,4
  847. _FMEM        dc.l    0
  848. fp        dc.l    0    ; save SnapShot file pointer
  849. DumpPath    dc.b    'DF1:'
  850. DumpName    dc.b    'SnapShot.TB',0
  851. SeekStore    dc.l    0
  852. TempAddr    dc.l    0    ; Storage for &TempStore
  853. TempStore    dc.l    0,0    ; Temporary storage for BPTR -> APTR
  854. TempSize    equ    *-TempStore
  855.  
  856.     cnop    0,4
  857.     ifd    AUTOREQ
  858. TAttr:                ; Text attributes for font
  859.     dc.l    TName        ; name of font
  860.     dc.w    TOPAZ_EIGHTY    ; font size
  861.     dc.b    FS_NORMAL    ; font style
  862.     dc.b    FPF_ROMFONT    ; font preferences
  863. TName:
  864.     dc.b    'topaz',0
  865.     cnop    0,4
  866.  
  867. IText1:             ; Text definitions for AutoReq call
  868.     dc.b    3,0,RP_JAM1,0    ; front & back pens, drawmode and filler byte
  869.     dc.w    6,4        ; XY origin relative to container TopLeft
  870.     dc.l    TAttr        ; font pointer or NULL for default
  871.     dc.l    ITextText1    ; pointer to text
  872.     dc.l    IText2        ; next IntuiText structure
  873. ITextText1:
  874.     dc.b    'Program:',0
  875.     cnop 0,4
  876. IText2:
  877.     dc.b    3,0,RP_JAM1,0
  878.     dc.w    78,4
  879.     dc.l    TAttr
  880. PName    dc.l    0
  881.     dc.l    IText3
  882.     cnop    0,4
  883. IText3:
  884.     dc.b    3,0,RP_JAM1,0
  885.     dc.w    55,16
  886.     dc.l    TAttr
  887.     dc.l    ITextText3
  888.     dc.l    IText4
  889. ITextText3:
  890.     dc.b    'I caught a GURU!',0
  891.     cnop 0,4
  892. IText4:
  893.     dc.b    3,0,RP_JAM1,0
  894.     dc.w    20,28
  895.     dc.l    TAttr
  896.     dc.l    ITextText4
  897.     dc.l    NULL
  898. ITextText4:
  899.     dc.b    'Should I make a SnapShot?',0
  900.     cnop 0,4
  901. IText5:
  902.     dc.b    3,0,RP_JAM1,0
  903.     dc.w    6,4
  904.     dc.l    TAttr
  905.     dc.l    ITextText5
  906.     dc.l    NULL
  907. ITextText5:
  908.     dc.b    'YES',0
  909.     cnop 0,4
  910. IText6:
  911.     dc.b    3,0,RP_JAM1,0
  912.     dc.w    7,4
  913.     dc.l    TAttr
  914.     dc.l    ITextText6
  915.     dc.l    NULL
  916. ITextText6:
  917.     dc.b    'NO',0
  918.     endc
  919.  
  920.     cnop 0,4
  921.  
  922. *--------------------------------------------------------------------------
  923. * New IFF chunk format -
  924. *    PGTB = Program Traceback, header for chunk
  925. *    FAIL = reason for and environment of crash
  926. *    REGS = registers at time of crash, including PC and CCR
  927. *    VERS = version, revision, name of this program
  928. *    STAK = ENTIRE stack at time of crash or, alternately,
  929. *    the top and bottom 4k if the stack used is > 8k
  930. *    UDAT = optional user data dump (if _ONGURU is set to a
  931. *    function pointer in the user's program)
  932. *--------------------------------------------------------------------------
  933.  
  934. PGTB        dc.b    'FORM'        ; required IFF header
  935. formLength    dc.l    0
  936.  
  937.         dc.b    'PGTB'
  938. Length        dc.l    0        ; length of chunk (in longwords)
  939.  
  940. subFAIL     dc.b    'FAIL'
  941. FAILlen     dc.l    9
  942. NameLen     dc.l    0        ; length of program name
  943. chunk_len_1    equ    *-PGTB
  944. Environment    dc.l    0        ; CPU (, Math)
  945. VBlankFreq    dc.l    0        ;    PAL = 50, NTSC = 60 (approx.)
  946. PowerSupFreq    dc.l    0        ; Europe = 50,    USA = 60 (approx.)
  947. Starter     dc.l    0        ; 0 = WB, -1 = CLI
  948. GURUNum     dc.l    0        ; cause of crash (GURU #)
  949. SegCount    dc.l    1        ; # hunks in seglist
  950. chunk_len_2    equ    *-Environment
  951.  
  952. subFMEM     dc.b    'FMEM'        ; FMEM - free memory at crash
  953.         dc.l    6
  954. chipAvail    dc.l    0        ; available chip memory
  955. chipMax     dc.l    0        ;    maximum    chip memory
  956. chipLargest    dc.l    0        ;    largest    chip memory
  957. fastAvail    dc.l    0        ; available fast memory
  958. fastMax     dc.l    0        ;    maximum    fast memory
  959. fastLargest    dc.l    0        ;    largest    fast memory
  960. FMEMlen     equ    *-subFMEM
  961.  
  962. subREGS     dc.b    'REGS'        ; REGS - register storage field
  963. REGSlen     dc.l    18
  964. GURUAddr    dc.l    0        ; PC at time of crash
  965. Flags        dc.l    0        ; Condition Code Register (CCR)
  966. DDump        dc.l    0,0,0,0,0,0,0,0    ; data registers
  967. ADump        dc.l    0,0,0,0,0,0,0    ; address registers
  968. A7Store     dc.l    0
  969.  
  970. subVERS     dc.b    'VERS'        ; VERS - program version field
  971.         dc.l    6
  972.         dc.l    VERSION     ; version #
  973.         dc.l    REVISION    ; revision #
  974.         dc.l    3        ; length of name of program
  975.         ifd    AUTOREQ
  976.          dc.b    'catch.o',0,0,0,0,0     ; name
  977.         endc
  978.         ifnd    AUTOREQ
  979.          dc.b    'catchnr.o',0,0,0    ; name
  980.         endc
  981.  
  982. subSTAK     dc.b    'STAK'        ; STAK - stack field
  983. STAKlen     dc.l    4
  984. Type        dc.l    0        ; 0 = Info
  985. StackTop    dc.l    0        ; top of stack pointer
  986. StackPtr    dc.l    0        ; current Stack Pointer
  987. StackLen    dc.l    0        ; # bytes used on stack
  988. chunk_len_3    equ    *-subREGS
  989.  
  990. STAK2        dc.b    'STAK'
  991. s2len        dc.l    1        ; length of subtype
  992.         dc.l    1        ; 1 = whole stack
  993. STAK2len    equ    *-STAK2
  994.  
  995. STAK3        dc.b    'STAK'
  996.         dc.l    1025
  997.         dc.l    2        ; 2 = top 4k of stack
  998. STAK3len    equ    *-STAK3
  999.  
  1000. STAK4        dc.b    'STAK'
  1001.         dc.l    1025
  1002.         dc.l    3        ; 3 = bottom 4k of stack
  1003. STAK4len    equ    *-STAK4
  1004.  
  1005. STAK5        dc.b    'STAK'
  1006. _STAKOffset    dc.l    0
  1007.         dc.l    4        ; 4 = user defined amount
  1008. STAK5len    equ    *-STAK5
  1009.  
  1010. UDAT        dc.b    'UDAT'
  1011.         dc.l    0
  1012. UDATlen     equ    *-UDAT
  1013.     endc
  1014.  
  1015.     END
  1016.  
  1017.